/*
 * MCP2515.c
 *
 * Created: 04.10.2012 11:36:34
 *  Author: bardbakk
 */ 
#include "SPI.h"
#include "MCP2515.h"
#include "definitions.h"
#include <stdio.h>
#include <avr/io.h>




uint8_t MCP2515_read(uint8_t address)
{
	uint8_t result;
	
	//Select the CAN-Controller
	BIT_CLEAR(PORTB, CAN_CS);
	
	// Send read command
	SPI_MasterTransmit(MCP_READ);
	
	// Send address
	SPI_MasterTransmit(address);
	
	// Read result
	result = SPI_MasterReceive();

	// Deselect CAN-controller
	BIT_SET(PORTB, CAN_CS); 
	
	return result;
}



void MCP2515_write(uint8_t address, uint8_t chr)
{	
	//Select the CAN-Controller
	BIT_CLEAR(PORTB, CAN_CS);
	
	// Send read command
	SPI_MasterTransmit(MCP_WRITE);
	
	// Send address
	SPI_MasterTransmit(address);
	
	//Send len bytes of data

	SPI_MasterTransmit(chr);
	
	
	// Deselect CAN-controller
	BIT_SET(PORTB, CAN_CS); 
}

void MCP2515_request_to_send(int buf)
{
	//Select the CAN-Controller
	BIT_CLEAR(PORTB, CAN_CS);
	
	// Send RTS command
	switch(buf)
	{
		case 0:
			SPI_MasterTransmit(MCP_RTS_TX0);
			break;
		case 1:	
			SPI_MasterTransmit(MCP_RTS_TX1);
			break;
		case 2:
			SPI_MasterTransmit(MCP_RTS_TX2);
			break;
		case 3:
			SPI_MasterTransmit(MCP_RTS_ALL);
			break;
	}
	
	// Deselect CAN-controller
	BIT_SET(PORTB, CAN_CS);
}

void MCP2515_bit_modify(uint8_t address, uint8_t mask, uint8_t data)
{
	//Select the CAN-Controller
	BIT_CLEAR(PORTB, CAN_CS);
	
	//Send bit modify command
	SPI_MasterTransmit(MCP_BITMOD);
	
	//Send address of register, mask and data
	SPI_MasterTransmit(address);
	SPI_MasterTransmit(mask);
	SPI_MasterTransmit(data);	
	
	// Deselect CAN-controller
	BIT_SET(PORTB, CAN_CS); 
}

void MCP2515_reset()
{
	//Select the CAN-Controller
	BIT_CLEAR(PORTB, CAN_CS);
	
	// Send reset command
	SPI_MasterTransmit(MCP_RESET);
	
	// Deselect CAN-controller
	BIT_SET(PORTB, CAN_CS); 
}

uint8_t MCP2515_read_status()
{
	uint8_t status;
	
	//Select the CAN-Controller
	BIT_CLEAR(PORTB, CAN_CS);
	
	// Send read status command
	SPI_MasterTransmit(MCP_READ_STATUS);
	
	//Read the status
	status = SPI_MasterReceive();
	
	// Deselect CAN-controller
	BIT_SET(PORTB, CAN_CS); 
	
	return status;
}

uint8_t MCP2515_init()
{
	uint8_t res;
	
	//Initialiser SPI
	SPI_init(); 
	
	MCP2515_reset();
	
	// Self-test
	res = MCP2515_read(MCP_CANSTAT);
	if ((res & MODE_MASK) != MODE_CONFIG) 
	{
		printf("MCP2515 is NOT in configuration mode after reset!\n");
		return 1;
	}
	// More initialization
	return 0;
}

